home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume20 / etherlib / part03 < prev    next >
Encoding:
Internet Message Format  |  1989-10-24  |  48.1 KB

  1. Subject:  v20i060:  User-level interface to Ethernet, Part03/03
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Alexander Dupuy <dupuy@cs.columbia.edu>
  7. Posting-number: Volume 20, Issue 60
  8. Archive-name: etherlib/part03
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 3 (of 3)."
  17. # Contents:  ./ether.3n ./src/nit3open.c ./src/nit4open.c ./tests/ctp.c
  18. #   ./tests/ethertest.c
  19. # Wrapped by rsalz@papaya.bbn.com on Wed Oct 25 16:37:32 1989
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f './ether.3n' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'./ether.3n'\"
  23. else
  24. echo shar: Extracting \"'./ether.3n'\" \(7564 characters\)
  25. sed "s/^X//" >'./ether.3n' <<'END_OF_FILE'
  26. X.TH ETHER 3N  "29 June 1989"
  27. X.SH NAME
  28. Xether \- raw ethernet access functions
  29. X.SH SYNOPSIS
  30. X.LP
  31. X.B #include <ether.h>
  32. X.LP
  33. X.nf
  34. X.ft B
  35. Xtypedef union etheraddr {
  36. X    char bytes[6];
  37. X    char shorts[3];
  38. X} ether_addr;
  39. X
  40. Xextern ether_addr ether_bcast_addr;
  41. X
  42. Xtypedef struct etherpacket {
  43. X    ether_addr dest;
  44. X    ether_addr src;
  45. X    char type[2];
  46. X    unsigned short pktlen;
  47. X    char \(**pktbuf;
  48. X} ether_packet;
  49. X
  50. Xtypedef struct ethervec {
  51. X    ether_addr dest;
  52. X    ether_addr src;
  53. X    char type[2];
  54. X    unsigned short iovcnt;
  55. X    struct iovec \(**iov;
  56. X} ether_vec;
  57. X.ft R
  58. X.fi
  59. X.LP
  60. X.nf
  61. X.ft B
  62. Xint ether_open(name, type, address)
  63. Xchar \(**name;
  64. Xint type;
  65. Xether_addr \(**address;
  66. X.ft R
  67. X.fi
  68. X.LP
  69. X.nf
  70. X.ft B
  71. Xchar \(**\(**ether_interfaces();
  72. X.ft R
  73. X.fi
  74. X.LP
  75. X.nf
  76. X.ft B
  77. Xether_addr \(**ether_address(fd, address)
  78. Xint fd;
  79. Xether_addr \(**address;
  80. X.ft R
  81. X.fi
  82. X.LP
  83. X.nf
  84. X.ft B
  85. Xether_addr \(**ether_intfaddr(name, address)
  86. Xchar \(**name;
  87. Xether_addr \(**address;
  88. X.ft R
  89. X.fi
  90. X.LP
  91. X.nf
  92. X.ft B
  93. Xint ether_write(fd, packet)
  94. Xint fd;
  95. Xether_packet \(**packet;
  96. X.ft R
  97. X.fi
  98. X.LP
  99. X.nf
  100. X.ft B
  101. Xint ether_read(fd, packet)
  102. Xint fd;
  103. Xether_packet \(**packet;
  104. X.ft R
  105. X.fi
  106. X.LP
  107. X.nf
  108. X.ft B
  109. Xint ether_blocking(fd, state)
  110. Xint fd;
  111. Xint state;
  112. X.ft R
  113. X.fi
  114. X.LP
  115. X.nf
  116. X.ft B
  117. Xint ether_send_self(fd)
  118. Xint fd;
  119. X.ft R
  120. X.fi
  121. X.LP
  122. X.nf
  123. X.ft B
  124. Xint ether_mcast_self(fd)
  125. Xint fd;
  126. X.ft R
  127. X.fi
  128. X.LP
  129. X.nf
  130. X.ft B
  131. Xint ether_bcast_self(fd)
  132. Xint fd;
  133. X.ft R
  134. X.fi
  135. X.LP
  136. X.nf
  137. X.ft B
  138. X#include <sys/types.h>
  139. X#include <sys/uio.h>
  140. X.ft R
  141. X.fi
  142. X.LP
  143. X.nf
  144. X.ft B
  145. Xint ether_writev(fd, packetvec)
  146. Xint fd;
  147. Xether_vec \(**packetvec;
  148. X.ft R
  149. X.fi
  150. X.LP
  151. X.nf
  152. X.ft B
  153. Xint ether_readv(fd, packetvec)
  154. Xint fd;
  155. Xether_vec \(**packetvec;
  156. X.ft R
  157. X.fi
  158. X.SH DESCRIPTION
  159. X.LP
  160. XThese functions provide access to the raw ethernet for user-level programs.  On
  161. XSuns, they are implemented using
  162. X.BR \s-1NIT\s0 (4p)
  163. X(network interface tap).  While they do not provide the full
  164. Xfunctionality of
  165. X.SM NIT
  166. X, these functions do run on both the socket- and streams-based 
  167. X.SM NIT
  168. Ximplementations.  On Ultrix systems, they are implemented using
  169. X.SM DLI
  170. X(data link interface).  On 4.3 BSD systems, they are implemented using the
  171. XStanford enetfilter device driver in the user-contributed software.  These
  172. Xfunctions are not designed to be used for ethernet monitoring, but rather for
  173. Xprograms implementing ethernet protocols such as
  174. X.SM RARP
  175. X, or the Ethernet configuration test protocol. 
  176. X.LP
  177. XThe function ether_open returns a file descriptor for the ethernet device
  178. Xspecified by
  179. X.I name
  180. X(such as "le0" or "ie1").  If no name is given, the default ethernet interface
  181. Xis used.  Packets for the ethernet address
  182. X.I address
  183. Xwill be received in addition to packets for the local ethernet address and
  184. Xbroadcasts; this is useful for multicast protocols.  Superuser privilege is
  185. Xneeded to use this feature.  Only packets with a protocol type of
  186. X.I type
  187. Xwill be received or sent.  This value should be passed in host byte order, not
  188. Xin network byte order. 
  189. X.LP
  190. XIn order to allow some basic ethernet monitoring capability on Sun
  191. X.SM NIT
  192. X-based systems and BSD enetfilter systems, if
  193. X.I address
  194. Xis all zeros, or if
  195. X.I type
  196. Xis ETHER_ALLTYPES (defined in ether.h), address and/or type matching will be
  197. Xdisabled.  This will not work on Ultrix
  198. X.SM DLI
  199. X-based systems, so using the
  200. X.SM NIT
  201. Xinterface directly is nearly as portable, and gives better filtering and
  202. Xbuffering. 
  203. X.LP
  204. XThe ether_interfaces function can be used to determine the valid interface
  205. Xnames available.  It returns an array of strings (with the last element set to
  206. X\s-1NULL\s0), each entry of which is an ethernet interface name valid for use
  207. Xin ether_open. 
  208. X.LP
  209. XThe ether_address function returns the local ethernet address for the ethernet
  210. Xinterface on the file descriptor
  211. X.IR fd . 
  212. XThe result is stored in the structure given by
  213. X.IR address ;
  214. Xif none is given,
  215. X.IR malloc (3)
  216. Xis used to allocate space. 
  217. X.LP
  218. XThe ether_read and ether_write functions read or write a single ethernet
  219. Xpacket. When writing, the 
  220. X.IR dest ,
  221. X.I pktlen
  222. Xand
  223. X.I pktbuf
  224. Xfields must be provided; the
  225. X.I src
  226. Xand
  227. X.I type
  228. Xfields are set to the local ethernet address and the ethernet type passed
  229. Xto 
  230. X.IR ether_open (\|). 
  231. XWhen reading, only 
  232. X.I pktlen
  233. Xand
  234. X.I pktbuf
  235. Xare looked at; the
  236. X.IR src ,
  237. X.IR dest ,
  238. Xand
  239. X.I type
  240. Xfields are set from the packet on a successful return. If
  241. X.I pktbuf
  242. Xis non-\s-1NULL\s0, up to 
  243. X.I pktlen
  244. Xbytes will be read in to the buffer space specified by
  245. X.IR pktbuf . 
  246. XIf 
  247. X.I pktbuf
  248. Xis \s-1NULL\s0, 
  249. X.I pktlen
  250. Xis ignored and
  251. X.IR malloc (3)
  252. Xis used to allocate enough space for the packet.  The value of
  253. X.I pktlen
  254. Xis set to the lesser of its original value and the actual packet size
  255. X(exclusive of the ethernet header).  The size of the original ethernet packet
  256. Xis returned. 
  257. X.LP
  258. XThe ether_readv and ether_writev functions operate in the same way as
  259. Xether_read and ether_write, but use an interface like that provided by the
  260. Xreadv and writev system calls.  The
  261. X.I iov
  262. Xand
  263. X.I iovcnt
  264. Xfields specify the length and location of an array of struct iovec.  Each iovec
  265. Xentry specifies the base address and length of an area in memory where data is
  266. Xread from or written to.
  267. X.LP
  268. XThe ether_blocking function can be used to make the ethernet file descriptor
  269. X.I fd
  270. Xnon-blocking.  If 
  271. X.I state
  272. Xis zero, the file descriptor is set non-blocking with
  273. X.IR fcntl (2);
  274. Xif 
  275. X.I state
  276. Xis non-zero, the file descriptor is set to be blocking. 
  277. X.LP
  278. XThe ether_send_self, ether_mcast_self and ether_bcast_self functions return 1
  279. Xif the interface will receive packets that it sends to itself, multicasts or
  280. Xbroadcasts, respectively, and will return 0 if the interface will not receive
  281. Xsuch packets.
  282. X.LP
  283. XIn addition, there are a number of auxiliary routines for manipulating ethernet
  284. Xaddresses.  Although they are not documented here, the ether.h header file
  285. Xdescribes them.
  286. X.SH DIAGNOSTICS
  287. XAll functions which return an integer value return a negative number if there
  288. Xis an error.  A zero return indicates no error.  The ether_interfaces and
  289. Xether_addresses functions return \s-1NULL\s0 if there is an error.  All
  290. Xfunctions leave an error code in the external variable
  291. X.I errno
  292. Xif an error occurs.  If an attempt to read an ethernet file descriptor which
  293. Xhas been set to non-blocking mode fails because the operation would block,
  294. Xerrno will be set to EAGAIN (not EWOULDBLOCK). 
  295. X.SH BUGS
  296. XDoesn't support IEEE 802.3 based protocols. 
  297. X.LP
  298. XBecause of restrictions in the
  299. X.SM DLI
  300. Xand socket based
  301. X.SM NIT
  302. Ximplementations, the ether_open function may require superuser privilege on
  303. Xsome machines.  On SunOS 4.0 machines, it is sufficient to be able to open
  304. Xthe /dev/nit special file.  On machines with the Stanford enetfilter, it is
  305. Xsufficient to be able to open the interface's special file in /dev/enet/.
  306. X.LP
  307. XDue to limitations in the Stanford enetfilter, using select to determine if
  308. Xan ethernet device is ready to accept writes will always return true.  Also,
  309. Xusing ether_blocking(0) will not prevent blocking on writes.  Since writes
  310. Xalmost always complete quickly, this isn't a major problem, but applications
  311. Xmay block if the ethernet is jammed.
  312. X.LP
  313. XThe basic monitoring capabilities provided are a hack.  Something like
  314. X.SM NIT
  315. Xshould be standardized as a monitoring interface. 
  316. X.LP
  317. XThe auxiliary address routines should be better documented.
  318. X.SH SEE ALSO
  319. X.BR nit (4p),
  320. X.BR nit_if (4p),
  321. X.BR nit_pf (4p),
  322. X.BR enet (4),
  323. X.BR fcntl (2),
  324. X.BR fcntl (5)
  325. X.SH AUTHORS
  326. XAlexander Dupuy, Robert Mokry, Columbia University Computer Science Department.
  327. XThanks to Charlie Kim for ideas stolen from his ethernet access implementation.
  328. XSome of the auxiliary ethernet address routines are derived from code written
  329. Xby Philip Budne, Boston University Computer Science Department.
  330. END_OF_FILE
  331. if test 7564 -ne `wc -c <'./ether.3n'`; then
  332.     echo shar: \"'./ether.3n'\" unpacked with wrong size!
  333. fi
  334. # end of './ether.3n'
  335. fi
  336. if test -f './src/nit3open.c' -a "${1}" != "-c" ; then 
  337.   echo shar: Will not clobber existing file \"'./src/nit3open.c'\"
  338. else
  339. echo shar: Extracting \"'./src/nit3open.c'\" \(6958 characters\)
  340. sed "s/^X//" >'./src/nit3open.c' <<'END_OF_FILE'
  341. X/* $Id: nit3open.c,v 2.2 89/10/24 17:53:27 dupuy Exp $ */
  342. X
  343. X#include <sys/param.h>            /* NOFILE */
  344. X#include <sys/time.h>            /* timeval */
  345. X#include <sys/socket.h>            /* sockaddr_nit (sockaddr) */
  346. X#include <sys/ioctl.h>            /* ioctl */
  347. X
  348. X#include <net/nit.h>            /* sockaddr_nit */
  349. X#include <netinet/in.h>            /* htons */
  350. X
  351. X#include <strings.h>            /* strncpy */
  352. X#include <errno.h>            /* EWOULDBLOCK/EINVAL */
  353. X
  354. X#include "libether.h"
  355. X
  356. Xstruct timeval *ether_timeout;
  357. Xstruct timeval *ether_timestamp;
  358. X
  359. Xstatic ether_addr promiscuous;
  360. X
  361. Xstatic fd_set multicast;
  362. Xstatic gotlocal;
  363. Xstatic ether_addr local_addr;
  364. X
  365. Xunsigned _ether_types[NOFILE];
  366. Xether_addr _ether_multi_addrs[NOFILE];
  367. X
  368. X#define ether_type (_ether_types[fd])
  369. X#define multi_addr (_ether_multi_addrs[fd])
  370. X
  371. X/*
  372. X * Returns file descriptor for ethernet device by name ("ie0", "le0", etc.).
  373. X * If name is NULL, uses primary ethernet interface.  Will only receive
  374. X * packets of type specified.  Will receive packets for the ethernet address
  375. X * specified, or local ethernet address if NULL.  If there is an error,
  376. X * returns (-1) and the appropriate value is left in errno.  Normal return
  377. X * status zero. Requires superuser privilege.
  378. X */
  379. X
  380. Xint
  381. Xether_open (name, type, address)
  382. Xchar *name;
  383. Xunsigned type;
  384. Xether_addr *address;
  385. X{
  386. X    int fd;
  387. X    struct sockaddr_nit snit;
  388. X    struct nit_ioc nioc;
  389. X    char **interfaces;
  390. X    int saved_errno;
  391. X
  392. X    if (name == 0)
  393. X    {                    /* get default ethernet interface */
  394. X    interfaces = ether_interfaces ();
  395. X    if (interfaces == 0 || *interfaces == 0)
  396. X        return (-1);
  397. X
  398. X    name = *interfaces;        /* just use the first name in list */
  399. X    }
  400. X
  401. X    if ((fd = socket (AF_NIT, SOCK_RAW, NITPROTO_RAW)) < 0)
  402. X    {
  403. X#ifdef DEBUG
  404. X    perror ("ether_open: socket");
  405. X#endif
  406. X    return (-1);
  407. X    }
  408. X
  409. X    snit.snit_family = AF_NIT;
  410. X    (void) strncpy (snit.snit_ifname, name, NITIFSIZ);
  411. X
  412. X    if (bind (fd, (struct sockaddr *) &snit, sizeof (snit)) != 0)
  413. X    {
  414. X    saved_errno = errno;
  415. X#ifdef DEBUG
  416. X    perror ("ether_open: bind");
  417. X#endif
  418. X    (void) close (fd);
  419. X    errno = saved_errno;
  420. X    return (-1);
  421. X    }
  422. X
  423. X    bzero ((char *) &nioc, sizeof (nioc));
  424. X
  425. X    if (type != ETHER_ALLTYPES && type > ETHER_MAXTYPE)
  426. X    {
  427. X    (void) close (fd);
  428. X    errno = EINVAL;
  429. X    return (-1);
  430. X    }
  431. X
  432. X    nioc.nioc_bufalign = sizeof (long);
  433. X    nioc.nioc_chunksize = nioc.nioc_bufspace = ETHER_BUFSIZ;
  434. X    nioc.nioc_typetomatch =
  435. X    (type == ETHER_ALLTYPES) ? type : htons ((u_short) type);
  436. X    nioc.nioc_snaplen = ETHER_PKT + ETHER_MAX;
  437. X
  438. X    if (address == 0)            /* not a multicast address */
  439. X    {
  440. X    multicast.fds_bits[0] &= ~(1 << fd);
  441. X    nioc.nioc_flags = NF_TIMEOUT;
  442. X    }
  443. X    else                /* a multicast address */
  444. X    {
  445. X    if (ether_cmp (address, &promiscuous))
  446. X    {
  447. X        if (!ETHER_MCAST (address))
  448. X        {
  449. X#ifdef DEBUG
  450. X        (void) printf ("rejecting non-multicast address argument\n");
  451. X#endif
  452. X        (void) close (fd);
  453. X        errno = EINVAL;
  454. X        return (-1);
  455. X        }
  456. X
  457. X        multicast.fds_bits[0] |= (1 << fd);
  458. X        multi_addr = *address;
  459. X        if (gotlocal == 0)
  460. X        if (ether_address (fd, &local_addr) != NULL)
  461. X            gotlocal = 1;
  462. X    }
  463. X    else
  464. X        multicast.fds_bits[0] &= ~(1 << fd);
  465. X
  466. X    nioc.nioc_flags = NF_TIMEOUT | NF_PROMISC;
  467. X    }
  468. X
  469. X    if (ether_timeout != 0)        /* use specified value of timeout */
  470. X    nioc.nioc_timeout = *ether_timeout;
  471. X    else
  472. X    {                    /* then use default value of timeout */
  473. X    nioc.nioc_timeout.tv_sec = 0;
  474. X    nioc.nioc_timeout.tv_usec = 10000;
  475. X    }
  476. X
  477. X    if (ioctl (fd, SIOCSNIT, (char *) &nioc) != 0)
  478. X    {
  479. X    saved_errno = errno;
  480. X#ifdef DEBUG
  481. X    perror ("ether_open: ioctl SIOCSNIT");
  482. X#endif
  483. X    (void) close (fd);
  484. X    errno = saved_errno;
  485. X    return (-1);
  486. X    }
  487. X
  488. X    ether_type = type;
  489. X    return (fd);
  490. X}
  491. X
  492. X
  493. X#ifdef DEBUG
  494. X
  495. Xvoid
  496. Xdump_nit_hdr (nitbuf)
  497. Xstruct nit_hdr *nitbuf;
  498. X{
  499. X    switch (nitbuf->nh_state)
  500. X    {
  501. X      case NIT_QUIET:
  502. X    (void) printf ("ether_read: nit quiet\n");
  503. X    break;
  504. X
  505. X      case NIT_CATCH:
  506. X    (void) printf ("ether_read: nit catch: size %d\n", nitbuf->nh_datalen);
  507. X    break;
  508. X
  509. X      case NIT_NOMBUF:
  510. X    (void) printf ("ether_read: nit no mbufs: %d lost\n",
  511. X               nitbuf->nh_dropped);
  512. X    break;
  513. X
  514. X      case NIT_NOCLUSTER:
  515. X    (void) printf ("ether_read: nit no mclusters: %d lost\n",
  516. X               nitbuf->nh_dropped);
  517. X    break;
  518. X
  519. X      case NIT_NOSPACE:
  520. X    (void) printf ("ether_read: nit no bufspace: %d lost\n",
  521. X               nitbuf->nh_dropped);
  522. X    break;
  523. X
  524. X      case NIT_SEQNO:
  525. X    (void) printf ("ether_read: nit sequence # %d\n", nitbuf->nh_seqno);
  526. X    break;
  527. X
  528. X      default:
  529. X    (void) printf ("ether_read: bad nit header state: %d\n",
  530. X               nitbuf->nh_state);
  531. X    break;
  532. X    }
  533. X}
  534. X
  535. X#endif
  536. X
  537. X
  538. X/*
  539. X * Reads and returns a single packet, filling in all fields.  If pktbuf is
  540. X * NULL, a buffer is allocated for it.    If pktbuf is not NULL, the function
  541. X * assumes that pktbuf is large enough to hold pktlen bytes.  Since read() may
  542. X * return several packets at a time, ether_read() has to buffer them as well.
  543. X * Since socket based nit doesn't handle multicast addresses, we have to check
  544. X * them at the user level.
  545. X *
  546. X * NOTE - the buffering code is non-reentrant if the same fd is used.
  547. X */
  548. X
  549. Xstatic long ether_buf[NOFILE][ETHER_BUFSIZ / sizeof (long)];
  550. Xstatic int ether_buflen[NOFILE];
  551. Xstatic char *ether_bufptr[NOFILE];
  552. X
  553. X#define buf    (ether_buf[fd])
  554. X#define buflen    (ether_buflen[fd])
  555. X#define bufptr    (ether_bufptr[fd])
  556. X
  557. X_ether_next_packet (fd, bufp)
  558. Xint fd;
  559. Xchar **bufp;
  560. X{
  561. X    struct nit_hdr *nitbuf;
  562. X    ether_addr *pbuf;
  563. X
  564. X    if (bufptr == 0)            /* easier than static initialization */
  565. X    bufptr = (char *) buf;
  566. X
  567. X    for (;;)
  568. X    {
  569. X    if ((bufptr - (char *) buf) >= buflen)
  570. X    {                /* then buffer is used up */
  571. X        buflen = read (fd, (char *) buf, ETHER_BUFSIZ);
  572. X        bufptr = (char *) buf;
  573. X        if (buflen <= 0)
  574. X        {
  575. X        if (errno == EWOULDBLOCK)
  576. X            errno = EAGAIN;
  577. X        return (-1);
  578. X        }
  579. X    }
  580. X
  581. X    /*
  582. X     * This assignment is safe, since nit guarantees requested alignment
  583. X     */
  584. X
  585. X    nitbuf = (struct nit_hdr *) bufptr;
  586. X    while (nitbuf->nh_state != NIT_CATCH)
  587. X    {
  588. X#ifdef DEBUG
  589. X        dump_nit_hdr (nitbuf);
  590. X#endif
  591. X        nitbuf++;
  592. X        if ((char *) nitbuf - (char *) buf > buflen)
  593. X        {
  594. X#ifdef DEBUG
  595. X        (void) printf ("truncated nit_hdr struct in buffer\n");
  596. X#endif
  597. X        continue;
  598. X        }
  599. X    }
  600. X#ifdef DEBUG
  601. X    dump_nit_hdr (nitbuf);
  602. X#endif
  603. X    /*
  604. X     * Set bufptr to next nit_hdr, pbuf to start of ether packet
  605. X     */
  606. X
  607. X    bufptr = ((char *) (pbuf = (ether_addr *) (nitbuf + 1)))
  608. X        + nitbuf->nh_datalen + pad (nitbuf->nh_datalen);
  609. X
  610. X    /*
  611. X     * Check for local, broadcast or multicast packet 
  612. X     */
  613. X
  614. X    if ((multicast.fds_bits[0] & (1 << fd))
  615. X        && (ETHER_MCAST (pbuf) ? (ether_cmp (pbuf, ðer_bcast_addr)
  616. X                      && ether_cmp (pbuf, &multi_addr))
  617. X        : ether_cmp (pbuf, &local_addr)))
  618. X    {
  619. X#ifdef DEBUG
  620. X        (void) printf ("discarding incorrectly addressed packet\n");
  621. X#endif
  622. X        continue;
  623. X    }
  624. X
  625. X    if (nitbuf->nh_wirelen > nitbuf->nh_datalen)
  626. X    {
  627. X#ifdef DEBUG
  628. X        (void) printf ("discarding truncated packet\n");
  629. X#endif
  630. X        continue;
  631. X    }
  632. X    break;
  633. X    }
  634. X
  635. X    if (nitbuf->nh_wirelen - ETHER_PKT < 0)
  636. X    errno = EBADMSG;
  637. X    else
  638. X    *bufp = (char *) pbuf;
  639. X
  640. X    ether_timestamp = &nitbuf->nh_timestamp;
  641. X
  642. X    return (nitbuf->nh_wirelen - ETHER_PKT);
  643. X}
  644. END_OF_FILE
  645. if test 6958 -ne `wc -c <'./src/nit3open.c'`; then
  646.     echo shar: \"'./src/nit3open.c'\" unpacked with wrong size!
  647. fi
  648. # end of './src/nit3open.c'
  649. fi
  650. if test -f './src/nit4open.c' -a "${1}" != "-c" ; then 
  651.   echo shar: Will not clobber existing file \"'./src/nit4open.c'\"
  652. else
  653. echo shar: Extracting \"'./src/nit4open.c'\" \(5614 characters\)
  654. sed "s/^X//" >'./src/nit4open.c' <<'END_OF_FILE'
  655. X/* $Id: nit4open.c,v 2.1 89/10/23 15:42:59 dupuy Exp $ */
  656. X
  657. X#include <sys/file.h>            /* O_RDWR */
  658. X#include <sys/stropts.h>        /* RMSGD */
  659. X#include <sys/types.h>            /* NIOCBIND (u_long) */
  660. X#include <sys/time.h>            /* NIOCBIND (timeval) */
  661. X#include <sys/socket.h>            /* ifreq (sockaddr) */
  662. X
  663. X#include <net/if.h>            /* ifreq */
  664. X#include <net/nit_if.h>            /* NIOCBIND */
  665. X#include <net/nit_pf.h>            /* NIOCSETF */
  666. X#include <net/packetfilt.h>        /* packetfilt */
  667. X
  668. X#include <netinet/in.h>            /* htons */
  669. X
  670. X#include <strings.h>            /* strncpy */
  671. X#include <errno.h>            /* EMFILE/EINVAL */
  672. X
  673. X#include "libether.h"
  674. X
  675. X#ifndef NIT_DEV
  676. X#define NIT_DEV "/dev/nit"
  677. X#endif
  678. X
  679. Xstatic ether_addr promiscuous;
  680. X
  681. Xunsigned _ether_types[FD_SETSIZE];
  682. X
  683. X#define ether_type (_ether_types[fd])
  684. X
  685. Xstatic int
  686. Xnioctl (fd, cmd, ptr)
  687. Xint fd;
  688. Xint cmd;
  689. Xchar *ptr;
  690. X{
  691. X    int saved_errno;
  692. X
  693. X    if (ioctl (fd, cmd, ptr) < 0)
  694. X    {
  695. X    saved_errno = errno;
  696. X#ifdef DEBUG
  697. X    switch (cmd)
  698. X    {
  699. X      case I_SRDOPT:
  700. X        perror ("ether_open: ioctl (I_SRDOPT)");
  701. X        break;
  702. X      case I_PUSH:
  703. X        perror ("ether_open: ioctl (I_PUSH)");
  704. X        break;
  705. X      case NIOCSETF:
  706. X        perror ("ether_open: ioctl (NIOCSETF)");
  707. X        break;
  708. X      case NIOCBIND:
  709. X        perror ("ether_open: ioctl (NIOCBIND)");
  710. X        break;
  711. X      case NIOCSFLAGS:
  712. X        perror ("ether_open: ioctl (NIOCSFLAGS)");
  713. X        break;
  714. X      default:
  715. X        perror ("ether_open: ioctl (????)");
  716. X        break;
  717. X    }
  718. X#endif
  719. X    (void) close (fd);
  720. X    errno = saved_errno;
  721. X    return (-1);
  722. X    }
  723. X
  724. X    return (0);
  725. X}
  726. X
  727. X
  728. X/*
  729. X * Returns file descriptor for ethernet device by name ("ie0", "le0", etc.).
  730. X * If name is NULL, uses primary ethernet interface.  Will only receive
  731. X * packets of type specified.  Will receive packets for the ethernet address
  732. X * specified, or local ethernet address if NULL.  If there is an error,
  733. X * returns (-1) and the appropriate value is left in errno.  Normal return
  734. X * status zero. Requires superuser privilege.
  735. X */
  736. X
  737. Xint
  738. Xether_open (name, type, address)
  739. Xchar *name;
  740. Xunsigned type;
  741. Xether_addr *address;
  742. X{
  743. X    int fd;
  744. X    struct ifreq ifr;
  745. X    struct packetfilt filter;
  746. X    unsigned short *fptr = 0;
  747. X    char **interfaces;
  748. X    register int i;
  749. X
  750. X    if (name == 0)            /* get default ethernet interface */
  751. X    {
  752. X    interfaces = ether_interfaces ();
  753. X    if (interfaces == 0 || *interfaces == 0)
  754. X        return (-1);
  755. X
  756. X    name = *interfaces;        /* just use the first name in list */
  757. X    }
  758. X
  759. X    if ((fd = open (NIT_DEV, O_RDWR)) < 0)
  760. X    {
  761. X#ifdef DEBUG
  762. X    perror (NIT_DEV);
  763. X#endif
  764. X    return (-1);
  765. X    }
  766. X
  767. X    if (fd >= FD_SETSIZE)        /* not worth making it work here */
  768. X    {
  769. X    (void) close (fd);
  770. X    errno = EMFILE;
  771. X    return (-1);
  772. X    }
  773. X
  774. X    /* arrange to get discrete messages from the stream */
  775. X
  776. X    if (nioctl (fd, I_SRDOPT, (char *) RMSGD) < 0)
  777. X    return (-1);
  778. X
  779. X    /* set up filter */
  780. X
  781. X    if (type != ETHER_ALLTYPES)        /* hack for NIT features */
  782. X    {
  783. X    if (type > ETHER_MAXTYPE)
  784. X    {
  785. X        (void) close (fd);
  786. X        errno = EINVAL;
  787. X        return (-1);
  788. X    }
  789. X
  790. X    if (nioctl (fd, I_PUSH, "pf") < 0)
  791. X        return (-1);
  792. X
  793. X    fptr = &filter.Pf_Filter[0];
  794. X
  795. X    *fptr++ = ENF_PUSHWORD + ETHER_TYPE / sizeof (short);
  796. X    *fptr++ = ENF_PUSHLIT | ENF_EQ;
  797. X    *fptr++ = htons ((u_short) type);
  798. X
  799. X    filter.Pf_FilterLen = fptr - &filter.Pf_Filter[0];
  800. X    filter.Pf_Priority = 1;        /* unimportant, so long as < 2 */
  801. X
  802. X    if (nioctl (fd, NIOCSETF, (char *) &filter) < 0)
  803. X        return (-1);
  804. X    }
  805. X
  806. X    /*
  807. X     * We defer the bind until after we've pushed the filter to prevent our
  808. X     * being flooded with extraneous packets
  809. X     */
  810. X
  811. X    (void) strncpy (ifr.ifr_name, name, sizeof (ifr.ifr_name));
  812. X
  813. X    if (nioctl (fd, NIOCBIND, (char *) &ifr) < 0)
  814. X    return (-1);
  815. X
  816. X    if (address != 0)
  817. X    {
  818. X    if (ether_cmp (address, &promiscuous))
  819. X    {
  820. X#ifndef MULTICAST
  821. X        ether_addr local_addr;
  822. X#endif
  823. X        if (!ETHER_MCAST (address))
  824. X        {
  825. X#ifdef DEBUG
  826. X        (void) printf ("rejecting non-multicast address argument\n");
  827. X#endif
  828. X        (void) close (fd);
  829. X        errno = EINVAL;
  830. X        return (-1);
  831. X        }
  832. X
  833. X#ifdef MULTICAST
  834. X        /* #error not clear how to set multicast addresses */
  835. X        exit (-1);            /* die die die */
  836. X#else
  837. X
  838. X        /*
  839. X         * Enable address matching filter before we go into promiscuous
  840. X         * mode.  We have to do this after the bind, since we can't get
  841. X         * the interface address until then.
  842. X         */
  843. X
  844. X        (void) ether_address (fd, &local_addr);
  845. X
  846. X        /* may not have pushed packet filtering module yet */
  847. X
  848. X        if (fptr == 0)
  849. X        if (nioctl (fd, I_PUSH, "pf") < 0)
  850. X            return (-1);
  851. X
  852. X        fptr = &filter.Pf_Filter[0];
  853. X
  854. X        if (type != ETHER_ALLTYPES)    /* hack for NIT features */
  855. X        {
  856. X        *fptr++ = ENF_PUSHWORD + ETHER_TYPE / sizeof (short);
  857. X        *fptr++ = ENF_PUSHLIT;
  858. X        *fptr++ = htons ((u_short) type);
  859. X        *fptr++ = ENF_CAND;
  860. X        }
  861. X
  862. X        for (i = 0; i < 3; i++)    /* compare addresses in 3 shorts */
  863. X        {
  864. X        *fptr++ = ENF_PUSHWORD + ETHER_DST / sizeof (short) + i;
  865. X        *fptr++ = ENF_PUSHLIT | ENF_EQ;
  866. X        *fptr++ = address->shorts[i];
  867. X        *fptr++ = ENF_PUSHWORD + ETHER_DST / sizeof (short) + i;
  868. X        *fptr++ = ENF_PUSHLIT | ENF_EQ;
  869. X        *fptr++ = ether_bcast_addr.shorts[i];
  870. X        *fptr++ = ENF_OR;
  871. X        *fptr++ = ENF_PUSHWORD + ETHER_DST / sizeof (short) + i;
  872. X        *fptr++ = ENF_PUSHLIT | ENF_EQ;
  873. X        *fptr++ = local_addr.shorts[i];
  874. X        *fptr++ = ENF_CNOR;
  875. X        }
  876. X
  877. X        filter.Pf_FilterLen = fptr - &filter.Pf_Filter[0];
  878. X        filter.Pf_Priority = 1;    /* unimportant, so long as < 2 */
  879. X
  880. X        if (nioctl (fd, NIOCSETF, (char *) &filter) < 0)
  881. X        return (-1);
  882. X
  883. X#endif                    /* MULTICAST */
  884. X
  885. X    }
  886. X
  887. X#ifdef MULTICAST
  888. X    else                /* only promiscuous if requested */
  889. X#endif
  890. X
  891. X    {                /* go into promiscuous mode */
  892. X        long flag;
  893. X
  894. X        flag = NI_PROMISC;
  895. X
  896. X        if (nioctl (fd, NIOCSFLAGS, (char *) &flag) < 0)
  897. X        return (-1);
  898. X    }
  899. X    }
  900. X
  901. X    ether_type = type;
  902. X    return (fd);
  903. X}
  904. END_OF_FILE
  905. if test 5614 -ne `wc -c <'./src/nit4open.c'`; then
  906.     echo shar: \"'./src/nit4open.c'\" unpacked with wrong size!
  907. fi
  908. # end of './src/nit4open.c'
  909. fi
  910. if test -f './tests/ctp.c' -a "${1}" != "-c" ; then 
  911.   echo shar: Will not clobber existing file \"'./tests/ctp.c'\"
  912. else
  913. echo shar: Extracting \"'./tests/ctp.c'\" \(14485 characters\)
  914. sed "s/^X//" >'./tests/ctp.c' <<'END_OF_FILE'
  915. X/* $Id: ctp.c,v 1.3 89/10/24 17:54:23 dupuy Exp $ */
  916. X
  917. X/*
  918. X * ctp - ethernet configuration test protocol program
  919. X */
  920. X
  921. X/*
  922. X * derived from ethertools/ctp.c
  923. X *
  924. X * Copyright (c) 1988 Philip L. Budne and The Trustees of Boston University All
  925. X * Rights Reserved
  926. X *
  927. X * Permission is granted to any individual or institution to use, copy, or
  928. X * redistribute this software so long as it is not sold for profit, provided
  929. X * that this notice and the original copyright notices are retained.  Boston
  930. X * University makes no representations about the suitability of this software
  931. X * for any purpose.  It is provided "as is" without express or implied
  932. X * warranty.
  933. X */
  934. X
  935. X#include <stdio.h>
  936. X#include <signal.h>
  937. X#include <errno.h>
  938. X
  939. Xextern int errno;
  940. X
  941. X#include "ctp.h"
  942. X
  943. X#ifdef SIGABRT
  944. X#define sigtype void
  945. X#else
  946. X#define sigtype int
  947. X#endif
  948. X
  949. Xstruct timeval *ether_timestamp;    /* timestamp from 3.x NIT, maybe */
  950. X
  951. X/*
  952. X * Ethernet related variables
  953. X */
  954. X
  955. Xint nomulticast = 0;
  956. X
  957. X#ifdef __STDC__
  958. Xether_addr ctpmulticast = {{0xcf, 0x0, 0x0, 0x0, 0x0, 0x0}};
  959. X
  960. X#else
  961. Xether_addr ctpmulticast;
  962. Xunsigned char bytes[6] = {0xcf, 0x0, 0x0, 0x0, 0x0, 0x0};
  963. X
  964. X#endif
  965. X
  966. Xether_addr localaddr;            /* our ethernet address */
  967. X
  968. X/*
  969. X * CTP statistics
  970. X */
  971. X
  972. X#define NBUCKETS 733            /* prime # of buckets */
  973. X#define hash(addr) \
  974. X (((addr)->shorts[1] + ((addr)->shorts[1] ^ (addr)->shorts[2])) % NBUCKETS)
  975. X
  976. Xint nsent = 0;
  977. X
  978. Xstruct
  979. X{
  980. X    int nrecvd;                /* total count */
  981. X    int highseq;            /* highest seq seen */
  982. X    int outofseq;            /* number recvd out of sequence */
  983. X    int min;
  984. X    int max;                /* min and max times */
  985. X    int sum;                /* sum of times */
  986. X
  987. X    int valid;                /* is this a used entry */
  988. X    ether_addr eaddr;            /* ethernet address for this count */
  989. X}
  990. X       stats[NBUCKETS + 1];
  991. X
  992. Xint lastseq = 0;
  993. Xint seq = 0;
  994. X
  995. X/*
  996. X * Program options and arguments
  997. X */
  998. X
  999. Xchar *interface = NULL;            /* interface to use */
  1000. Xint count = -1;                /* number of packets to send */
  1001. Xint noreturn = 0;            /* don't force final forward back */
  1002. Xint packlen = ETHER_MIN;        /* default total packet length */
  1003. Xint slptim = 1000;            /* sleep time in ms */
  1004. X
  1005. X/*
  1006. X * Other functions and variables
  1007. X */
  1008. X
  1009. Xint pid;                /* our pid */
  1010. Xint tosend = 0;
  1011. X
  1012. Xshort swaps ();
  1013. Xsigtype resend ();
  1014. Xsigtype die ();
  1015. Xvoid printstats ();
  1016. Xctp_reply *output_packet ();
  1017. Xvoid input_packet ();
  1018. X
  1019. X
  1020. Xmain (argc, argv)
  1021. Xint argc;
  1022. Xchar *argv[];
  1023. X{
  1024. X    int efd;
  1025. X    int optind;
  1026. X    ether_addr path[MAXPATH];
  1027. X    int pathcount = 0;
  1028. X    ether_packet outpkt;
  1029. X    ctp_packet outpktbuf;
  1030. X    ctp_reply *reply;            /* pointer to ctp_reply in outpkt */
  1031. X    struct itimerval interval;
  1032. X
  1033. X    /*
  1034. X     * Get program options
  1035. X     */
  1036. X
  1037. X    if ((optind = getoptions (argc, argv)) < 0 || optind >= argc)
  1038. X    {
  1039. X    (void) fprintf (stderr,
  1040. X      "Usage: %s [-c count] [-n] [-i intf] [-l len] [-s sleep] addr ...\n",
  1041. X            argv[0]);
  1042. X    exit (1);
  1043. X    }
  1044. X
  1045. X    /*
  1046. X     * Open ethernet interface
  1047. X     */
  1048. X
  1049. X    if (interface == NULL)
  1050. X    {
  1051. X    char **intfs;
  1052. X
  1053. X    if ((intfs = ether_interfaces ()) == NULL)
  1054. X    {
  1055. X        perror ("ether_interfaces");
  1056. X        exit (1);
  1057. X    }
  1058. X
  1059. X    interface = *intfs;
  1060. X    }
  1061. X
  1062. X#ifndef __STDC__
  1063. X    (void) bcopy ((char *) bytes, (char *) ctpmulticast.bytes, sizeof (bytes));
  1064. X#endif
  1065. X
  1066. X    if ((efd = ether_open (interface, CTPTYPE, &ctpmulticast)) < 0)
  1067. X    {
  1068. X    /* try again w/o multicast, for enetfilter systems */
  1069. X
  1070. X    nomulticast++;
  1071. X
  1072. X    if ((efd = ether_open (interface, CTPTYPE, (ether_addr *) 0)) < 0)
  1073. X    {
  1074. X        perror (interface);
  1075. X        exit (1);
  1076. X    }
  1077. X    }
  1078. X
  1079. X    /*
  1080. X     * Set non-blocking, so that we can select and loop
  1081. X     */
  1082. X
  1083. X    if (ether_blocking (efd, 0) != 0)
  1084. X    {
  1085. X    perror ("ether_block");
  1086. X    exit (1);
  1087. X    }
  1088. X
  1089. X    /*
  1090. X     * Get local interface address and process id
  1091. X     */
  1092. X
  1093. X    if (ether_address (efd, &localaddr) == NULL)
  1094. X    {
  1095. X    perror ("ether_address");
  1096. X    exit (1);
  1097. X    }
  1098. X
  1099. X    (void) printf ("%s address %s\n", interface, ether_ntoa (&localaddr));
  1100. X
  1101. X    pid = getpid ();            /* so we can identify our packets */
  1102. X
  1103. X    /*
  1104. X     * Set up forwarding path for CTP packet
  1105. X     */
  1106. X
  1107. X    pathcount = 0;
  1108. X    while (optind < argc && pathcount < MAXPATH && argv[optind] != NULL)
  1109. X    {
  1110. X    if (strcmp (argv[optind], "MULTICAST") == 0)
  1111. X        path[pathcount] = ctpmulticast;
  1112. X
  1113. X    else if (strcmp (argv[optind], "BROADCAST") == 0)
  1114. X        path[pathcount] = ether_bcast_addr;
  1115. X
  1116. X    else if (!ether_host2e (argv[optind], &path[pathcount]))
  1117. X    {
  1118. X        extern char *sys_errlist[];
  1119. X        int saved_errno = errno;
  1120. X
  1121. X        (void) puts ("");
  1122. X        (void) fflush (stdout);
  1123. X        if (errno == ENOENT)
  1124. X        (void) fprintf (stderr, "%s: unknown host %s\n",
  1125. X                argv[0], argv[optind]);
  1126. X        else
  1127. X        (void) fprintf (stderr, "%s: can't get address for %s: %s\n",
  1128. X                argv[0], argv[optind],
  1129. X                sys_errlist[saved_errno]);
  1130. X
  1131. X        exit (1);
  1132. X    }
  1133. X
  1134. X    (void) printf ("%s%s (%s)", ((pathcount > 0) ? "\n    " : "CTP "),
  1135. X               argv[optind], ether_ntoa (&path[pathcount]));
  1136. X
  1137. X    pathcount++;
  1138. X    optind++;
  1139. X    }
  1140. X
  1141. X    if (pathcount == MAXPATH)
  1142. X    {
  1143. X    fputs (": ", stdout);
  1144. X    (void) fflush (stdout);
  1145. X    (void) fprintf (stderr, "Too many hosts in path (%d)\n", MAXPATH);
  1146. X    exit (1);
  1147. X    }
  1148. X
  1149. X    /*
  1150. X     * Build output packet
  1151. X     */
  1152. X
  1153. X    reply = output_packet (efd, &outpkt, &outpktbuf, path, pathcount);
  1154. X
  1155. X    /*
  1156. X     * Set up signal handlers and timers
  1157. X     */
  1158. X
  1159. X    (void) signal (SIGALRM, resend);
  1160. X    (void) signal (SIGINT, die);
  1161. X    (void) signal (SIGHUP, die);
  1162. X    (void) signal (SIGTERM, die);
  1163. X
  1164. X    interval.it_interval.tv_sec = slptim / 1000;
  1165. X    interval.it_interval.tv_usec = slptim % 1000;
  1166. X    interval.it_value.tv_sec = slptim / 1000;
  1167. X    interval.it_value.tv_usec = slptim % 1000;
  1168. X
  1169. X    if (setitimer (ITIMER_REAL, &interval, (struct itimerval *) 0) < 0)
  1170. X    {
  1171. X    perror ("setitimer");
  1172. X    exit (1);
  1173. X    }
  1174. X
  1175. X    /*
  1176. X     * Loop checking for packets
  1177. X     */
  1178. X
  1179. X    while (count != 0)
  1180. X    {
  1181. X    fd_set fdset;
  1182. X
  1183. X    if (tosend > 0)
  1184. X    {
  1185. X        tosend--;
  1186. X
  1187. X        reply->seq = seq++;
  1188. X
  1189. X        /*
  1190. X         * It's safe to cast reply->sendt, since that will be long aligned
  1191. X         */
  1192. X
  1193. X        (void) gettimeofday ((struct timeval *) reply->sendt,
  1194. X                 (struct timezone *) 0);
  1195. X
  1196. X        if (ether_write (efd, &outpkt) < 0)
  1197. X        {
  1198. X        perror ("ether_read");
  1199. X        exit (1);
  1200. X        }
  1201. X
  1202. X        nsent++;
  1203. X        count--;
  1204. X    }
  1205. X
  1206. X    FD_ZERO (&fdset);
  1207. X    FD_SET (efd, &fdset);
  1208. X
  1209. X    while (tosend == 0)
  1210. X    {
  1211. X        ether_packet pkt;
  1212. X        ctp_packet pktbuf;
  1213. X        struct timeval tv;
  1214. X
  1215. X        pkt.pktbuf = (char *) &pktbuf;
  1216. X        pkt.pktlen = sizeof (pktbuf);
  1217. X
  1218. X        if (select (efd + 1, param (&fdset), param (0), param (0),
  1219. X            (struct timeval *) 0) < 0)
  1220. X        {
  1221. X        if (errno == EINTR)
  1222. X            break;        /* from while loop */
  1223. X
  1224. X        perror ("select");
  1225. X        exit (1);
  1226. X        }
  1227. X
  1228. X        for (;;)            /* while packets can be read */
  1229. X        {
  1230. X        if (ether_read (efd, &pkt) < 0)
  1231. X        {
  1232. X            if (errno == EAGAIN)
  1233. X            break;        /* from for loop */
  1234. X
  1235. X            perror ("ether_read");
  1236. X            exit (1);
  1237. X        }
  1238. X
  1239. X        /*
  1240. X         * Use 3.x NIT timestamp if present, since latency is terrible
  1241. X         */
  1242. X
  1243. X        if (ether_timestamp)
  1244. X            tv = *ether_timestamp;
  1245. X        else
  1246. X            (void) gettimeofday (&tv, (struct timezone *) 0);
  1247. X
  1248. X        input_packet (&pkt, &pktbuf, &tv);
  1249. X        }
  1250. X    }
  1251. X    }
  1252. X
  1253. X    printstats ();
  1254. X    exit (0);
  1255. X}
  1256. X
  1257. Xctp_reply *
  1258. Xoutput_packet (efd, pkt, ctp, path, pathcount)
  1259. Xint efd;
  1260. Xether_packet *pkt;
  1261. Xctp_packet *ctp;
  1262. Xether_addr path[];
  1263. Xint pathcount;
  1264. X{
  1265. X    ctp_forward *forward;
  1266. X    ctp_reply *reply;
  1267. X    int i;
  1268. X
  1269. X    ctp->skip = 0;
  1270. X
  1271. X    /*
  1272. X     * Since ctp is long aligned, and the data offset is 2, we are safe
  1273. X     */
  1274. X
  1275. X    forward = (ctp_forward *) ctp->data;
  1276. X    for (i = 1; i < pathcount; i++)
  1277. X    {
  1278. X    forward->function = swaps (CTP_FWD);
  1279. X    forward->addr = path[i];
  1280. X    forward++;
  1281. X    }
  1282. X
  1283. X    /* ensure packet gets back -- append forward to ourselves if needed */
  1284. X
  1285. X    if (!noreturn && ether_cmp (&path[pathcount - 1], &localaddr)
  1286. X    && (ether_cmp (&path[pathcount - 1], ðer_bcast_addr)
  1287. X        || !ether_bcast_self (efd) || pathcount == 1
  1288. X        || ether_cmp (&path[pathcount - 2], &localaddr))
  1289. X    && (nomulticast || ether_cmp (&path[pathcount - 1], &ctpmulticast)
  1290. X        || !ether_mcast_self (efd) || pathcount == 1
  1291. X        || ether_cmp (&path[pathcount - 2], &localaddr)))
  1292. X    {
  1293. X    forward->function = swaps (CTP_FWD);
  1294. X    forward->addr = localaddr;
  1295. X    forward++;
  1296. X    }
  1297. X
  1298. X    reply = (ctp_reply *) forward;
  1299. X
  1300. X    i = ((char *) (reply + 1)) - (char *) ctp;
  1301. X
  1302. X    if (i > packlen)
  1303. X    if (i > ETHER_MAX)
  1304. X    {
  1305. X        (void) fputs (": ", stdout);
  1306. X        (void) fflush (stdout);
  1307. X        (void) fprintf (stderr, "Packet too large without data (%d)\n", i);
  1308. X        exit (1);
  1309. X    }
  1310. X    else
  1311. X        packlen = i;
  1312. X
  1313. X    (void) printf (": %d data bytes (%d total)\n", packlen - i, packlen + 14);
  1314. X    (void) fflush (stdout);
  1315. X
  1316. X    reply->function = swaps (CTP_REP);    /* create reply data */
  1317. X    reply->pid = pid;
  1318. X
  1319. X    pkt->dest = path[0];        /* fill in ether packet header */
  1320. X    pkt->pktbuf = (char *) ctp;
  1321. X    pkt->pktlen = packlen;
  1322. X
  1323. X    return (reply);            /* return pointer to reply struct */
  1324. X}
  1325. X
  1326. X
  1327. Xsigtype
  1328. Xresend ()
  1329. X{
  1330. X    tosend++;
  1331. X}
  1332. X
  1333. Xsigtype
  1334. Xdie ()
  1335. X{
  1336. X    puts ("");
  1337. X    printstats ();
  1338. X    exit (0);
  1339. X}
  1340. X
  1341. Xvoid
  1342. Xprintstats ()
  1343. X{
  1344. X    int bucket = 0;
  1345. X    int lastbucket = -1;
  1346. X    int min = ((unsigned) -1) >> 1;
  1347. X    int max = -1;
  1348. X    int nrecvd = 0;
  1349. X    int sum = 0;
  1350. X
  1351. X    (void) printf ("----CTP Statistics----\n");
  1352. X    (void) printf ("%d packet%s transmitted", nsent,
  1353. X           (nsent == 1 ? "" : "s"));
  1354. X
  1355. X    for (;;)
  1356. X    {
  1357. X    while (stats[bucket].valid == 0 && bucket < NBUCKETS)
  1358. X        bucket++;
  1359. X
  1360. X    if (lastbucket != -1
  1361. X        && (bucket != NBUCKETS || stats[lastbucket].nrecvd != nrecvd))
  1362. X    {
  1363. X        char hostaddr[ETHERSTRLEN];
  1364. X        char host[MAXHOSTNAMELEN];
  1365. X
  1366. X        (void) ether_e2a (&stats[lastbucket].eaddr, hostaddr);
  1367. X
  1368. X        (void) printf ("\n  %d received from ", stats[lastbucket].nrecvd);
  1369. X
  1370. X        if (ether_e2host (&stats[lastbucket].eaddr, host) == NULL)
  1371. X        (void) fputs (hostaddr, stdout);
  1372. X        else
  1373. X        (void) printf ("%s (%s)", host, hostaddr);
  1374. X
  1375. X        if (nsent - stats[lastbucket].nrecvd < 0)
  1376. X        (void) puts ("");
  1377. X        else
  1378. X        (void) printf (", %d%% packet loss\n", 100 *
  1379. X                   (nsent - stats[lastbucket].nrecvd) / nsent);
  1380. X        if (stats[lastbucket].nrecvd > 0)
  1381. X        (void)
  1382. X            printf ("  round-trip (ms)  min/avg/max = %d/%d/%d",
  1383. X                stats[lastbucket].min,
  1384. X                stats[lastbucket].sum / stats[lastbucket].nrecvd,
  1385. X                stats[lastbucket].max);
  1386. X    }
  1387. X
  1388. X    if (bucket == NBUCKETS)
  1389. X        break;            /* done with loop */
  1390. X
  1391. X    lastbucket = bucket;
  1392. X
  1393. X    if (min > stats[bucket].min)
  1394. X        min = stats[bucket].min;
  1395. X    if (max < stats[bucket].max)
  1396. X        max = stats[bucket].max;
  1397. X
  1398. X    nrecvd += stats[bucket].nrecvd;
  1399. X    sum += stats[bucket].sum;
  1400. X
  1401. X    bucket++;
  1402. X    }
  1403. X
  1404. X    if (lastbucket == -1 || stats[lastbucket].nrecvd == nrecvd)
  1405. X    {
  1406. X    (void) printf (", %d received", nrecvd);
  1407. X
  1408. X    if (nsent - nrecvd < 0)
  1409. X        (void) puts ("");
  1410. X    else
  1411. X        (void) printf (", %d%% packet loss\n",
  1412. X               100 * (nsent - nrecvd) / nsent);
  1413. X    }
  1414. X    else
  1415. X    fputs ("\noverall ", stdout);
  1416. X
  1417. X    if (nrecvd > 0)
  1418. X    (void) printf ("round-trip (ms)     min/avg/max = %d/%d/%d\n",
  1419. X               min, sum / nrecvd, max);
  1420. X}
  1421. X
  1422. Xvoid
  1423. Xinput_packet (pkt, ctp, tv)
  1424. Xether_packet *pkt;
  1425. Xctp_packet *ctp;
  1426. Xstruct timeval *tv;
  1427. X{
  1428. X    short skip;
  1429. X    ctp_reply *reply;
  1430. X    int ms;
  1431. X    int bucket;
  1432. X
  1433. X    skip = swaps (ctp->skip);        /* fetch skip */
  1434. X
  1435. X    if (skip & 1)            /* if skip is odd, we are unaligned */
  1436. X    return;
  1437. X
  1438. X    /*
  1439. X     * Since ctp is long aligned, and skip is not odd, this is safe
  1440. X     */
  1441. X
  1442. X    reply = (ctp_reply *) &ctp->data[skip];
  1443. X
  1444. X    if (pkt->pktlen - skip - 2 < 2)    /* no room for function */
  1445. X    return;
  1446. X
  1447. X    switch (swaps (reply->function))
  1448. X    {
  1449. X      case CTP_REP:            /* reply */
  1450. X    break;
  1451. X
  1452. X      case CTP_FWD:            /* XXX - should really process this */
  1453. X    return;
  1454. X
  1455. X      default:                /* probably a byteswapped function */
  1456. X    return;
  1457. X    }
  1458. X
  1459. X    if (pkt->pktlen - skip - 2 < sizeof (ctp_reply))
  1460. X    return;
  1461. X
  1462. X    if (reply->pid != pid)        /* not our packet */
  1463. X    return;
  1464. X
  1465. X    (void) printf ("%d bytes from %s: seq=%d time=", pkt->pktlen + ETHER_PKT,
  1466. X           ether_ntoa (&pkt->src), reply->seq);
  1467. X
  1468. X    /*
  1469. X     * It's safe to cast reply->sendt, since that will be long aligned
  1470. X     */
  1471. X
  1472. X    if ((ms = delta (tv, (struct timeval *) reply->sendt)) < 0)
  1473. X    {
  1474. X    (void) printf ("(%d ms)!!!\n", ms);
  1475. X    ms = 0;                /* time must have jumped back, yuck */
  1476. X    }
  1477. X    else
  1478. X    (void) printf ("%d ms\n", ms);
  1479. X
  1480. X    (void) fflush (stdout);
  1481. X
  1482. X    bucket = hash (&pkt->src);
  1483. X
  1484. X    while (stats[bucket].valid && ether_cmp (&stats[bucket].eaddr, &pkt->src))
  1485. X    if (++bucket >= NBUCKETS)
  1486. X        bucket = 0;
  1487. X
  1488. X    if (!stats[bucket].valid)        /* initialize new bucket */
  1489. X    {
  1490. X    stats[bucket].nrecvd = 0;
  1491. X    stats[bucket].highseq = 0;
  1492. X    stats[bucket].outofseq = 0;
  1493. X    stats[bucket].min = ((unsigned) -1) >> 1;
  1494. X    stats[bucket].max = -1;
  1495. X    stats[bucket].sum = 0;
  1496. X    stats[bucket].valid = 1;
  1497. X    stats[bucket].eaddr = pkt->src;
  1498. X    }
  1499. X
  1500. X    stats[bucket].nrecvd++;
  1501. X
  1502. X    if (reply->seq != lastseq && reply->seq != lastseq + 1)
  1503. X    stats[bucket].outofseq++;
  1504. X    lastseq = reply->seq;
  1505. X    if (reply->seq > stats[bucket].highseq)
  1506. X    stats[bucket].highseq = reply->seq;
  1507. X
  1508. X    if (ms > stats[bucket].max)
  1509. X    stats[bucket].max = ms;
  1510. X    if (ms < stats[bucket].min)
  1511. X    stats[bucket].min = ms;
  1512. X    stats[bucket].sum += ms;
  1513. X}
  1514. X
  1515. Xdelta (a, b)
  1516. Xstruct timeval *a;
  1517. Xstruct timeval *b;
  1518. X{
  1519. X    long usec;
  1520. X    long sec;
  1521. X
  1522. X    usec = a->tv_usec - b->tv_usec;
  1523. X    sec = a->tv_sec - b->tv_sec;
  1524. X
  1525. X    if (usec < 0)
  1526. X    {
  1527. X    sec--;
  1528. X    usec += 1000000;
  1529. X    }
  1530. X
  1531. X    usec += 500;            /* round to ms */
  1532. X    sec = sec * 1000 + usec / 1000;    /* get ms */
  1533. X
  1534. X    return (sec);
  1535. X}                    /* delta */
  1536. X
  1537. X
  1538. Xgetoptions (argc, argv)
  1539. Xint argc;
  1540. Xchar *argv[];
  1541. X{
  1542. X    extern char *optarg;
  1543. X    extern int optind;
  1544. X    int opt;
  1545. X    int errs;
  1546. X
  1547. X    errs = 0;
  1548. X    while ((opt = getopt (argc, argv, "c:i:l:ns:")) != EOF)
  1549. X    {
  1550. X    switch (opt)
  1551. X    {
  1552. X      case 'c':
  1553. X        if ((count = atoi (optarg)) <= 0)
  1554. X        {
  1555. X        errs++;
  1556. X        (void) fprintf (stderr, "invalid packet count: %s\n", optarg);
  1557. X        }
  1558. X        break;
  1559. X
  1560. X      case 'i':
  1561. X        interface = optarg;
  1562. X        break;
  1563. X
  1564. X      case 'l':
  1565. X        if ((packlen = atoi (optarg)) <= 0)
  1566. X        {
  1567. X        errs++;
  1568. X        (void) fprintf (stderr, "invalid packet length: %s\n", optarg);
  1569. X        }
  1570. X        else if (packlen < ETHER_MIN)
  1571. X        {
  1572. X        (void) fprintf (stderr,
  1573. X                "packet length %s increased to minimum %d\n",
  1574. X                optarg, ETHER_MIN);
  1575. X        packlen = ETHER_MIN;
  1576. X        }
  1577. X        else if (packlen > ETHER_MAX)
  1578. X        {
  1579. X        (void) fprintf (stderr,
  1580. X                "packet length %s decreased to maximum %d\n",
  1581. X                optarg, ETHER_MAX);
  1582. X        packlen = ETHER_MAX;
  1583. X        }
  1584. X        break;
  1585. X
  1586. X      case 'n':
  1587. X        noreturn ^= 1;
  1588. X        break;
  1589. X
  1590. X      case 's':
  1591. X        slptim = atoi (optarg);
  1592. X        break;
  1593. X
  1594. X      default:
  1595. X        errs++;
  1596. X    }
  1597. X    }
  1598. X
  1599. X    if (errs)
  1600. X    return (-1);
  1601. X    else
  1602. X    return (optind);
  1603. X}
  1604. X
  1605. X
  1606. Xshort
  1607. Xswaps (word)
  1608. Xunsigned short word;
  1609. X{
  1610. X    static int swap = -1;
  1611. X
  1612. X    if (swap < 0)
  1613. X    {
  1614. X    short test = 0x0100;
  1615. X    swap = *(char *) &test;
  1616. X    }
  1617. X
  1618. X    if (swap)
  1619. X    return (word >> 8 | (word & 0xff) << 8);
  1620. X    else
  1621. X    return (word);
  1622. X}
  1623. END_OF_FILE
  1624. if test 14485 -ne `wc -c <'./tests/ctp.c'`; then
  1625.     echo shar: \"'./tests/ctp.c'\" unpacked with wrong size!
  1626. fi
  1627. # end of './tests/ctp.c'
  1628. fi
  1629. if test -f './tests/ethertest.c' -a "${1}" != "-c" ; then 
  1630.   echo shar: Will not clobber existing file \"'./tests/ethertest.c'\"
  1631. else
  1632. echo shar: Extracting \"'./tests/ethertest.c'\" \(9445 characters\)
  1633. sed "s/^X//" >'./tests/ethertest.c' <<'END_OF_FILE'
  1634. X/* $Id: ethertest.c,v 1.3 89/10/24 17:54:39 dupuy Exp $ */
  1635. X
  1636. X#include <stdio.h>
  1637. X#include <strings.h>            /* strcmp */
  1638. X
  1639. X#include <sys/param.h>            /* MAXHOSTNAMELEN */
  1640. X#include <sys/uio.h>            /* iov */
  1641. X#include <sys/socket.h>
  1642. X
  1643. X#include <errno.h>            /* EAGAIN */
  1644. X#include <netdb.h>            /* hostent */
  1645. X
  1646. X#include <netinet/in.h>            /* in_addr */
  1647. X
  1648. X#include "ether.h"
  1649. X
  1650. X#if defined(lint) && defined (ultrix)
  1651. Xvoid bcopy ();
  1652. Xvoid perror ();
  1653. Xvoid exit ();
  1654. Xunsigned sleep ();
  1655. X#endif
  1656. X
  1657. X#if !defined (sun) && !defined (ultrix)
  1658. Xextern uid_t getuid ();
  1659. X#endif
  1660. X
  1661. X#define offsetof(type,mem) ((unsigned) &(((type *) 0)->mem))
  1662. X
  1663. Xchar hello[] = "hello,";
  1664. Xchar world[] = " world";
  1665. Xstruct iovec iov[2] = {{hello, 6}, {world, 7}};
  1666. Xchar helloworld[] = "hello, world";
  1667. Xstruct iovec iov2[1] = {{helloworld, 13}};
  1668. X
  1669. X#ifdef __STDC__
  1670. Xether_addr multicast = {{ 0x0f, 0x0f, 0x0f, 0xfe, 0xfe, 0x00 }};
  1671. X#else
  1672. Xether_addr multicast;
  1673. Xunsigned char bytes[6] = { 0x0f, 0x0f, 0x0f, 0xfe, 0xfe, 0x00 };
  1674. X#endif
  1675. Xchar mcastname1[] = "0f:0F:f:Fe:fE:0";
  1676. Xchar mcastname2[] = "0f-0F-f-Fe-fE-0";
  1677. X
  1678. Xether_vec packetv;
  1679. Xether_packet packet;
  1680. X
  1681. Xchar *inet_n2a ();
  1682. X
  1683. Xextern int errno;
  1684. X
  1685. Xmain ()
  1686. X{
  1687. X    char hostname[MAXHOSTNAMELEN + 1];
  1688. X    char *hname = NULL;
  1689. X    struct hostent *hdata;
  1690. X    ether_addr eaddress;
  1691. X    ether_addr eaddress2;
  1692. X    ether_addr eaddress3;
  1693. X    char **intfs;
  1694. X    int uid;
  1695. X    int i = ETHER_SRC;
  1696. X
  1697. X    /*
  1698. X     * Initialize union
  1699. X     */
  1700. X
  1701. X#ifndef __STDC__
  1702. X    (void) bcopy ((char *) bytes, (char *) multicast.bytes, sizeof (bytes));
  1703. X#endif
  1704. X
  1705. X    /*
  1706. X     * Test some structures for compiler sanity
  1707. X     */
  1708. X
  1709. X    if (i != sizeof (ether_addr))
  1710. X    (void) fprintf (stderr, "WARNING!!! sizeof (ether_addr) = %d\n",
  1711. X            sizeof (ether_addr));
  1712. X    if (ETHER_PKT != offsetof (ether_packet, type[2]))
  1713. X    (void) fprintf (stderr, "WARNING!!! offset of ether_packet = %d\n",
  1714. X            offsetof (ether_packet, type[2]));
  1715. X
  1716. X#ifdef __GNUC__
  1717. X    (void) printf ("ether_addr alignment = %d, ether_packet alignment = %d\n",
  1718. X           __alignof (ether_addr), __alignof (ether_packet));
  1719. X#endif
  1720. X
  1721. X    /*
  1722. X     * Get the canonical hostname
  1723. X     */
  1724. X
  1725. X    if (gethostname (hostname, sizeof (hostname)) < 0)
  1726. X    perror ("gethostname");
  1727. X    else
  1728. X    {
  1729. X    hname = hostname;
  1730. X
  1731. X    if ((hdata = gethostbyname (hostname)) == 0)
  1732. X        (void) fprintf (stderr, "host info for %s not found\n", hostname);
  1733. X    else
  1734. X    {
  1735. X        hname = hdata->h_name;
  1736. X
  1737. X        if ((hdata = gethostbyaddr (hdata->h_addr, hdata->h_length,
  1738. X                    hdata->h_addrtype)) == 0)
  1739. X        (void) fprintf (stderr, "%s address does not match\n", hname);
  1740. X        else
  1741. X        hname = hdata->h_name;
  1742. X
  1743. X    }
  1744. X    }
  1745. X
  1746. X    if (hname)
  1747. X    (void) printf ("%s ethertest\n", hname);
  1748. X
  1749. X    /*
  1750. X     * Get the ethernet interface names and test some utility functions
  1751. X     */
  1752. X
  1753. X    if ((intfs = ether_interfaces ()) == NULL)
  1754. X    {
  1755. X    perror ("ether_interfaces");
  1756. X    exit (1);
  1757. X    }
  1758. X
  1759. X    if (hname)
  1760. X    {
  1761. X    if (ether_host2e (hostname, &eaddress) == NULL)
  1762. X        (void) fprintf (stderr, "ether_h2e failed\n");
  1763. X    else
  1764. X        (void) printf ("%s: %s\n", hostname, ether_ntoa (&eaddress));
  1765. X    }
  1766. X
  1767. X    if (hdata)
  1768. X    {
  1769. X    struct in_addr ipaddr;
  1770. X
  1771. X    (void) bcopy (hdata->h_addr, (char *) &ipaddr, sizeof (ipaddr));
  1772. X    if (ether_hostent2e (hdata, &eaddress2) == NULL)
  1773. X        (void) fprintf (stderr, "ether_he2e failed\n");
  1774. X
  1775. X    else if (bcmp ((char *) &eaddress, (char *) &eaddress2,
  1776. X               sizeof (ether_addr)))
  1777. X        (void) printf ("%s: %s\n", hdata->h_name, ether_ntoa (&eaddress2));
  1778. X
  1779. X    if (ether_ip2e (&ipaddr, &eaddress3) == NULL)
  1780. X        perror ("ether_ip2e");
  1781. X
  1782. X    else if (bcmp ((char *) &eaddress3, (char *) &eaddress2,
  1783. X               sizeof (ether_addr)))
  1784. X        (void) printf ("%s: %s\n", inet_n2a (ipaddr),
  1785. X               ether_ntoa (&eaddress3));
  1786. X    }
  1787. X
  1788. X    uid = getuid ();
  1789. X
  1790. X    /*
  1791. X     * Loop through the interfaces, testing functions
  1792. X     */
  1793. X
  1794. X    for (i = 0; intfs[i]; i++)
  1795. X    {
  1796. X    ether_addr address;
  1797. X    int fd;
  1798. X    int self;
  1799. X
  1800. X    (void) printf ("%s: ", intfs[i]);
  1801. X    (void) fflush (stdout);
  1802. X
  1803. X    if ((fd = ether_open (intfs[i], 0xf0f0, (ether_addr *) NULL)) < 0)
  1804. X        perror ("open");
  1805. X    else
  1806. X    {
  1807. X        struct in_addr ipaddr;
  1808. X        char hostname2[MAXHOSTNAMELEN + 1];
  1809. X
  1810. X        (void) setreuid (0, uid);
  1811. X
  1812. X        if (ether_address (fd, &address) == NULL)
  1813. X        perror ("address");
  1814. X        else
  1815. X        (void) printf ("%s\n", ether_ntoa (&address));
  1816. X
  1817. X        hostname2[MAXHOSTNAMELEN] = '\0';
  1818. X        if (ether_e2host (&address, hostname2) == NULL)
  1819. X        {
  1820. X        (void) fprintf (stderr, "ether_e2host failed\n");
  1821. X        if (ether_e2ip (&address, &ipaddr) == NULL)
  1822. X            (void) fprintf (stderr, "ether_e2ip failed\n");
  1823. X        }
  1824. X        else
  1825. X        {
  1826. X        if (ether_e2ip (&address, &ipaddr) == NULL)
  1827. X            (void) fprintf (stderr, "ether_e2ip failed\n");
  1828. X        else
  1829. X            (void) printf ("%s: %s\n", hostname2, inet_n2a (ipaddr));
  1830. X        }
  1831. X
  1832. X        self = ether_bcast_self (fd);
  1833. X
  1834. X        packet.pktbuf = "dlrow ,olleh";
  1835. X        packet.pktlen = 13;
  1836. X        bcopy ((char *) ðer_bcast_addr, (char *) &packet.dest,
  1837. X           sizeof (address));
  1838. X        if (ether_write (fd, &packet) < 0)
  1839. X        perror ("ether_write");
  1840. X
  1841. X        if (ether_blocking (fd, 0))
  1842. X        perror ("ether_blocking");
  1843. X
  1844. X        (void) sleep (1);
  1845. X
  1846. X        packetv.iov = iov2;
  1847. X        packetv.iovcnt = sizeof (iov2) / sizeof (struct iovec);
  1848. X
  1849. X        if (ether_readv (fd, &packetv) < 0)
  1850. X        {
  1851. X        if (errno != EAGAIN)
  1852. X            perror ("ether_readv");
  1853. X        else if (self == 0)
  1854. X            (void)
  1855. X            (void) printf ("%s",
  1856. X                  "interface cannot receive own broadcasts\n");
  1857. X        else
  1858. X            (void) fprintf (stderr, "%s %s\n",
  1859. X                    "interface cannot receive own broadcasts",
  1860. X                    "but thinks that it can!");
  1861. X        }
  1862. X        else if (strcmp (helloworld, "dlrow ,olleh"))
  1863. X        (void) fprintf (stderr,
  1864. X                "bcast_self test received garbled packet\n");
  1865. X
  1866. X        else if (bcmp ((char *) &packetv.src, (char *) &address,
  1867. X               sizeof (ether_addr)))
  1868. X            (void) fprintf (stderr, "WARNING: source address %s!\n",
  1869. X                    ether_e2a (&packetv.src, (char *) 0));
  1870. X        else if (self == 1)
  1871. X        {
  1872. X        (void) printf ("%s",
  1873. X                   "interface will receive own broadcasts\n");
  1874. X        }
  1875. X        else
  1876. X        {
  1877. X        (void) fprintf (stderr, "%s %s\n",
  1878. X                "interface will receive own broadcasts",
  1879. X                "but doesn't think that it can!");
  1880. X        }
  1881. X
  1882. X        self = ether_send_self (fd);
  1883. X
  1884. X        packetv.iov = iov;
  1885. X        packetv.iovcnt = sizeof (iov) / sizeof (struct iovec);
  1886. X
  1887. X        bcopy ((char *) &address, (char *) &packetv.dest, sizeof (address));
  1888. X        if (ether_writev (fd, &packetv) < 0)
  1889. X        perror ("ether_writev");
  1890. X
  1891. X        (void) sleep (1);
  1892. X
  1893. X        packet.pktbuf = NULL;
  1894. X        if (ether_read (fd, &packet) < 0)
  1895. X        {
  1896. X        if (errno != EAGAIN)
  1897. X            perror ("ether_read");
  1898. X        else if (self == 0)
  1899. X            (void) printf ("%s",
  1900. X                   "interface cannot send packets to self\n");
  1901. X        else
  1902. X            (void) fprintf (stderr, "%s %s\n",
  1903. X                    "interface cannot send packets to self",
  1904. X                    "but thinks that it can!");
  1905. X        }
  1906. X        else if (strcmp (packet.pktbuf, "hello, world"))
  1907. X        (void) fprintf (stderr,
  1908. X                "send_self test received garbled packet\n");
  1909. X
  1910. X        else if (!bcmp ((char *) &packetv.src, (char *) &address,
  1911. X                sizeof (ether_addr)))
  1912. X            (void) fprintf (stderr, "WARNING: source address %s!\n",
  1913. X                    ether_ntoa (&packetv.src));
  1914. X
  1915. X        else if (self == 1)
  1916. X        {
  1917. X        (void) printf ("%s", "interface can send packets to self\n");
  1918. X        }
  1919. X        else
  1920. X        {
  1921. X        (void) fprintf (stderr, "%s %s\n",
  1922. X                "interface can send packets to self",
  1923. X                "but doesn't think that it can!");
  1924. X        }
  1925. X
  1926. X        (void) close (fd);
  1927. X
  1928. X        (void) setreuid (uid, 0);
  1929. X
  1930. X        if ((fd = ether_open (intfs[i], 0xf0f0, &multicast)) < 0)
  1931. X        (void) printf (
  1932. X               "interface does not support multicast reception\n");
  1933. X        else
  1934. X        {
  1935. X        (void) setreuid (0, uid);
  1936. X
  1937. X        self = ether_mcast_self (fd);
  1938. X
  1939. X        packet.pktbuf = "dlrow ,olleh";
  1940. X        packet.pktlen = 13;
  1941. X        bcopy ((char *) &multicast, (char *) &packet.dest,
  1942. X               sizeof (address));
  1943. X        if (ether_write (fd, &packet) < 0)
  1944. X            perror ("ether_write");
  1945. X
  1946. X        if (ether_blocking (fd, 0))
  1947. X            perror ("ether_blocking");
  1948. X
  1949. X        (void) sleep (1);
  1950. X
  1951. X        packetv.iov = iov2;
  1952. X        packetv.iovcnt = sizeof (iov2) / sizeof (struct iovec);
  1953. X
  1954. X        if (ether_readv (fd, &packetv) < 0)
  1955. X        {
  1956. X            if (errno != EAGAIN)
  1957. X            perror ("ether_readv");
  1958. X        else if (self == 0)
  1959. X            (void)
  1960. X            (void) printf ("%s",
  1961. X                  "interface cannot receive own multicasts\n");
  1962. X        else
  1963. X            (void) fprintf (stderr, "%s %s\n",
  1964. X                    "interface cannot receive own multicasts",
  1965. X                    "but thinks that it can!");
  1966. X        }
  1967. X        else if (strcmp (helloworld, "dlrow ,olleh"))
  1968. X            (void) fprintf (stderr,
  1969. X                  "mcast_self test received garbled packet\n");
  1970. X
  1971. X        else if (bcmp ((char *) &packetv.src, (char *) &address,
  1972. X                   sizeof (ether_addr)))
  1973. X            (void) fprintf (stderr, "WARNING: source address %s!\n",
  1974. X                    ether_ntoa (&packetv.src));
  1975. X
  1976. X        else if (self == 1)
  1977. X        {
  1978. X            (void) printf ("%s",
  1979. X                   "interface will receive own multicasts\n");
  1980. X        }
  1981. X        else
  1982. X        {
  1983. X            (void) fprintf (stderr, "%s %s\n",
  1984. X                    "interface will receive own multicasts",
  1985. X                    "but doesn't think that it can!");
  1986. X        }
  1987. X
  1988. X        (void) setreuid (uid, 0);
  1989. X        }
  1990. X    }
  1991. X    }
  1992. X
  1993. X    if (ether_cmp (&multicast, ether_aton (mcastname1)))
  1994. X    (void) fprintf (stderr, "ether_aton failed (%s)\n",
  1995. X            ether_ntoa (ether_aton (mcastname1)));
  1996. X
  1997. X    if (ether_cmp (&multicast, ether_a2e (mcastname2, &eaddress)))
  1998. X    (void) fprintf (stderr, "ether_a2e failed (%s)\n",
  1999. X            ether_ntoa (&eaddress));
  2000. X
  2001. X    return (0);
  2002. X}
  2003. X
  2004. Xchar *
  2005. Xinet_n2a (addr)
  2006. Xstruct in_addr addr;
  2007. X{
  2008. X#ifdef lint
  2009. X    char *sprintf ();
  2010. X#endif
  2011. X    static char buffer[16];
  2012. X    unsigned char *bytes;
  2013. X
  2014. X    bytes = (unsigned char *) &addr;
  2015. X    (void) sprintf (buffer, "%d.%d.%d.%d",
  2016. X            bytes[0], bytes[1], bytes[2], bytes[3]);
  2017. X
  2018. X    return (buffer);
  2019. X}
  2020. END_OF_FILE
  2021. if test 9445 -ne `wc -c <'./tests/ethertest.c'`; then
  2022.     echo shar: \"'./tests/ethertest.c'\" unpacked with wrong size!
  2023. fi
  2024. # end of './tests/ethertest.c'
  2025. fi
  2026. echo shar: End of archive 3 \(of 3\).
  2027. cp /dev/null ark3isdone
  2028. MISSING=""
  2029. for I in 1 2 3 ; do
  2030.     if test ! -f ark${I}isdone ; then
  2031.     MISSING="${MISSING} ${I}"
  2032.     fi
  2033. done
  2034. if test "${MISSING}" = "" ; then
  2035.     echo You have unpacked all 3 archives.
  2036.     rm -f ark[1-9]isdone
  2037. else
  2038.     echo You still need to unpack the following archives:
  2039.     echo "        " ${MISSING}
  2040. fi
  2041. ##  End of shell archive.
  2042. exit 0
  2043.